package com.huilian.iotbox.data.service.impl;

import com.huilian.iotbox.data.common.RedisLockKey;
import com.huilian.iotbox.data.dao.DeviceOnlineOfflineRecordCommonDao;
import com.huilian.iotbox.data.enums.DeviceOnlineOfflineRecordEnum;
import com.huilian.iotbox.data.po.DeviceOnlineOfflineRecord;
import com.huilian.iotbox.data.service.DeviceOnlineOfflineRecordCommonService;
import com.huilian.iotbox.data.utils.DateTimeUtils;
import com.huilian.iotbox.data.vo.DeviceVo;
import com.huilian.tool.weixin.service.WXSendMessageService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class DeviceOnlineOfflineRecordCommonServiceImpl implements DeviceOnlineOfflineRecordCommonService {

    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private WXSendMessageService wxSendMessageService;
    @Autowired
    private DeviceOnlineOfflineRecordCommonDao deviceOnlineOfflineRecordCommonDao;

    /**
     * 插入设备上下线信息
     *
     * @param deviceVo             设备信息
     * @param type                 上下线类型
     * @param connectedDateTime    开始时间
     * @param reason               原因
     */
    public void updateDeviceOnlineOfflineRecord(
            DeviceVo deviceVo,
            int type,
            Date connectedDateTime,
            String reason
    ) {
        String onlineOfflineRecordLockKey = String.format(RedisLockKey.ONLINE_OFFLINE_RECORD, deviceVo.getId());
        RLock lock = redissonClient.getLock(onlineOfflineRecordLockKey);
        try {
            final boolean tryLock = lock.tryLock(10, TimeUnit.SECONDS);
            if (tryLock) {
                log.info("updateDeviceOnlineOfflineRecord-获取到锁");

                DeviceOnlineOfflineRecord deviceOnlineOfflineRecord = new DeviceOnlineOfflineRecord();
                deviceOnlineOfflineRecord.setDeviceId(deviceVo.getId());

                if (DeviceOnlineOfflineRecordEnum.ONLINE.getCode() == type) {
                    final DeviceOnlineOfflineRecord existStartTime = deviceOnlineOfflineRecordCommonDao.findOneStartTime(deviceVo.getId(), DeviceOnlineOfflineRecordEnum.OFFLINE.getCode());
                    if (!StringUtils.isEmpty(existStartTime)) {

                        final String timeStr = DateTimeUtils.format(existStartTime.getStartTime());
                        final String time2Str = DateTimeUtils.format(connectedDateTime);

                        if (timeStr.equals(time2Str)) {
                            deviceOnlineOfflineRecordCommonDao.deleteById(existStartTime.getId());
                        } else {
                            DeviceOnlineOfflineRecord updateDOORecord = new DeviceOnlineOfflineRecord();
                            updateDOORecord.setId(existStartTime.getId());
                            updateDOORecord.setEndTime(connectedDateTime);
                            deviceOnlineOfflineRecordCommonDao.update(updateDOORecord);
                        }
                    }

                    deviceOnlineOfflineRecord.setStartTime(connectedDateTime);
                    deviceOnlineOfflineRecord.setType(type);
                    deviceOnlineOfflineRecordCommonDao.insert(deviceOnlineOfflineRecord);
                } else {
                    final DeviceOnlineOfflineRecord existStartTime = deviceOnlineOfflineRecordCommonDao.findOneRecentlyOnlineRecord(deviceVo.getId(), DeviceOnlineOfflineRecordEnum.ONLINE.getCode());

                    if (!StringUtils.isEmpty(existStartTime)) {
                        DeviceOnlineOfflineRecord updateDOORecord = new DeviceOnlineOfflineRecord();
                        updateDOORecord.setId(existStartTime.getId());
                        updateDOORecord.setEndTime(connectedDateTime);
                        deviceOnlineOfflineRecordCommonDao.update(updateDOORecord);
                    }
                    deviceOnlineOfflineRecord.setStartTime(connectedDateTime);
                    deviceOnlineOfflineRecord.setType(type);
                    deviceOnlineOfflineRecordCommonDao.insert(deviceOnlineOfflineRecord);
                }
            } else {
                log.warn("updateDeviceOnlineOfflineRecord-未获取到锁");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (!StringUtils.isEmpty(lock) && lock.isHeldByCurrentThread()) {
                lock.unlock();
                log.info("updateDeviceOnlineOfflineRecord-解锁成功");
            } else {
                log.error("updateDeviceOnlineOfflineRecord-lock is null or lock isNotHeldByCurrentThread");
            }
        }
    }
}
